<?php

namespace App\Http\Validate\Cruise;

use App\Http\Validate\AbstractBaseValidate;
use App\Models\Cruise\CruiseCheckSelfDetailModel;
use App\Models\Cruise\CruiseCheckSelfTaskModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Shop\ShopModel;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class CruiseCheckSelfTaskValidate extends AbstractBaseValidate
{
    function getRules(): array
    {
        // TODO: Implement getRules() method.
        return [
            "name"            => self::stringValidateBuild(true, 32, 1),
            "rule"            => self::intInValidateBuild(true, CruiseCheckSelfTaskModel::RULE_TEXT),
            "taskStartTime"   => self::timeValidateBuild(true, "Y-m-d"),
            "taskEndTime"     => self::timeValidateBuild(true, "Y-m-d"),
            "executeStartHis" => self::timeValidateBuild(true, "H:i:s"),
            "executeEndHis"   => self::timeValidateBuild(true, "H:i:s"),
            "templateId"      => ["required", "int", Rule::exists("cruise_template", "id")]
        ];
    }

    function getAttributes(): array
    {
        // TODO: Implement getAttributes() method.
        return [
            "taskIds.*" => "任务id"
        ];
    }

    function registerValidateRules(): void
    {
        // TODO: Implement registerValidateRules() method.
    }

    function getMessages(): array
    {
        // TODO: Implement getMessages() method.
        return [];
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ValidationException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws Exception
     */
    public static function insertValidate(array $params)
    {
        $templateType       = (int)CruiseTemplateModel::query()->where('id', $params['templateId'] ?? 0)->value('type');
        $validateFieldsRule = self::getSelfCheckModelValidateRules($templateType);

        return self::getInstance()->validate(
            array_keys($validateFieldsRule),
            $params,
            $validateFieldsRule,
            true,
            function ($params) {
                $params["taskStartTime"] = Carbon::createFromTimestamp(strtotime($params["taskStartTime"]))->startOfDay()->timestamp;
                $params["taskEndTime"]   = Carbon::createFromTimestamp(strtotime($params["taskEndTime"]))->endOfDay()->timestamp;

                if ($params["rule"] != CruiseCheckSelfTaskModel::RULE_DAY) {
                    $params["executeEndAfter"] = $params["executeStartBefore"] = 0;
                }

                return $params;
            }
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function updateValidate(array $params)
    {
        $templateType             = (int)CruiseTemplateModel::query()->where('id', $params['templateId'])
                                                            ->value('type');
        $validateFieldsRule       = self::getSelfCheckModelValidateRules($templateType);
        $validateFieldsRule["id"] = [
            "required",
            "int",
            Rule::exists("cruise_check_self_task", "id")->where("isDeleted", 0)
        ];

        return self::getInstance()->validate(
            array_keys($validateFieldsRule),
            $params,
            $validateFieldsRule,
            true,
            function ($params) {
                $params["taskStartTime"] = Carbon::createFromTimestamp(strtotime($params["taskStartTime"]))->startOfDay()->timestamp;
                $params["taskEndTime"]   = Carbon::createFromTimestamp(strtotime($params["taskEndTime"]))->endOfDay()->timestamp;

                if ($params["rule"] != CruiseCheckSelfTaskModel::RULE_DAY) {
                    $params["executeEndAfter"] = $params["executeStartBefore"] = 0;
                }

                return $params;
            }
        );
    }

    /**
     * @param int $templateType
     * @return array
     * @throws Exception
     */
    public static function getSelfCheckModelValidateRules(int $templateType): array
    {
        switch ($templateType) {
            case CruiseTemplateModel::TYPE_8:
                $validateFieldsRule = [
                    "name"               => self::stringValidateBuild(true, 32),
                    "rule"               => self::intInValidateBuild(true, CruiseCheckSelfTaskModel::RULE_TEXT),
                    "taskStartTime"      => "required|string|date_format:Y-m-d",
                    "taskEndTime"        => "required|string|date_format:Y-m-d",
                    "executeStartBefore" => [
                        "exclude_unless:rule," . CruiseCheckSelfTaskModel::RULE_DAY,
                        "required",
                        "int",
                        "min:1",
                        "max:24"
                    ],
                    "executeEndAfter"    => [
                        "exclude_unless:rule," . CruiseCheckSelfTaskModel::RULE_DAY,
                        "required",
                        "int",
                        "min:1",
                        "max:24"
                    ],
                    "templateId"         => "required|int",
                    "shopScope"          => self::intInValidateBuild(true, CruiseCheckSelfTaskModel::SHOP_SCOPE_TEXT),
                    "shopIds"            => [
                        "exclude_unless:shopScope," . CruiseCheckSelfTaskModel::SHOP_SCOPE_PART,
                        "array"
                    ],
                    "shopIds.*"          => [
                        "int",
                        "gt:0",
                        Rule::exists((new ShopModel())->getTable(), "id")->where("isDeleted", 0)
                    ]
                ];
                break;
            case CruiseTemplateModel::TYPE_5:
                $validateFieldsRule = [
                    "name"                    => self::stringValidateBuild(true, 32),
                    "rule"                    => self::intInValidateBuild(true, CruiseCheckSelfTaskModel::RULE_TEXT),
                    "taskStartTime"           => "required|string|date_format:Y-m-d",
                    "taskEndTime"             => "required|string|date_format:Y-m-d",
                    "templateId"              => "required|int",
                    "cruiseCheckCompanyIds"   => "array",
                    "cruiseCheckCompanyIds.*" => [
                        "int",
                        "distinct",
                        Rule::exists("cruise_check_company", "id")->where("isDeleted", 0)
                    ],
                    "executeStartHis"         => [
                        "required",
                        "date_format:H:i:s"
                    ],
                    "executeEndHis"           => [
                        "required",
                        "date_format:H:i:s",
                        "after:startTime"
                    ],
                ];
                break;
            default:
                throw new Exception("获取模板参数失败");
        }

        return $validateFieldsRule;
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function detailValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id"],
            $params,
            [
                "id" => Rule::exists("cruise_check_self_task", "id")->where("isDeleted", 0),
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function statusValidate(array $params)
    {
        return self::getInstance()->validate(
            ["id", "status"],
            $params,
            [
                "id"     => Rule::exists("cruise_check_self_task", "id")->where("isDeleted", 0),
                "status" => self::intInValidateBuild(true, CruiseCheckSelfTaskModel::STATUS_TEXT)
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function supplierTaskPreviewValidate(array $params)
    {
        return self::getInstance()->validate(
            [
                "cruiseCheckCompanyId",
//                "status"
            ],
            $params,
            [
                "cruiseCheckCompanyId" => Rule::exists("cruise_check_company", "id")->where("isDeleted", 0),
//                "status"               => self::intInValidateBuild(true, CruiseCheckSelfDetailModel::STATUS_TEXT)
            ]
        );
    }


    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function todayNotProduceValidate(array $params)
    {
        return self::getInstance()->validate(
            ["taskIds", "cruiseCheckCompanyId"],
            $params,
            [
                "cruiseCheckCompanyId" => [
                    "required",
                    "int",
                    Rule::exists("cruise_check_company", "id")->where("isDeleted", 0)
                ],
                "taskIds"              => "required|array",
                "taskIds.*"            => [
                    Rule::exists("cruise_check_self_task", "id")->where(function ($query) use ($params) {
                        $query->where("isDeleted", 0)
                              ->where("taskStartTime", "<=", time())
                              ->where("taskEndTime", ">", time() - 24 * 60 * 60);
                    }),
                    Rule::exists("cruise_check_self_task_company_mappings", "taskId")
                        ->where("cruiseCheckCompanyId", $params["cruiseCheckCompanyId"] ?? 0),
                    function ($attribute, $value, $fail) use ($params) {
                        $exists = CruiseCheckSelfDetailModel::query()
                                                            ->where("status", CruiseCheckSelfTaskModel::STATUS_ON)
                                                            ->where("taskId", $value)
                                                            ->where("cruiseCheckCompanyId",
                                                                $params["cruiseCheckCompanyId"] ?? 0)
                                                            ->where("date", date("Ymd", time()))
                                                            ->first();
                        if ($exists) {
                            $fail("选定 $attribute 无效");
                        }
                    },
                ]
            ]
        );
    }

    /**
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function supplierTaskDetailValidate(array $params)
    {
        return self::getInstance()->validate(
            ["taskId", "cruiseCheckCompanyId"],
            $params,
            [
                "cruiseCheckCompanyId" => [
                    "required",
                    "int",
                    Rule::exists("cruise_check_company", "id")->where("isDeleted", 0)
                ],
                "taskId"               => [
                    "required",
                    "int",
                    Rule::exists("cruise_check_self_task", "id")->where(function ($query) use ($params) {
                        $query->where("isDeleted", 0);
                    }),
                    Rule::exists("cruise_check_self_task_company_mappings", "taskId")
                        ->where("cruiseCheckCompanyId", $params["cruiseCheckCompanyId"] ?? 0)
                ]
            ]
        );
    }


    /**
     * 门店自检 - 自检任务列表校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function shopSelfCheckTaskListValidate(array $params)
    {
        return self::getInstance()->validate(
            [
                "shopId",
                "pageSize",
                "pageNum",
            ],
            $params,
            [
                "pageSize" => "required|int|min:1|max:100",
                "pageNum"  => "required|int|min:1",
                "state"    => self::intInValidateBuild(true, CruiseCheckSelfTaskModel::TYPE_8_STATE_TEXT),
                "shopId"   => [
                    "required",
                    "int",
                    Rule::exists((new ShopModel())->getTable(), "id")
                ]
            ]
        );
    }

    /**
     * 门店自检 - 自检任务详情校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function shopSelfCheckTaskDetailValidate(array $params)
    {
        return self::getInstance()->validate(
            [
                "shopId",
                "id",
            ],
            $params,
            [
                "id"     => [
                    "required",
                    "int",
                    Rule::exists((new CruiseCheckSelfTaskModel())->getTable(), "id")
                ],
                "shopId" => [
                    "required",
                    "int",
                    Rule::exists((new ShopModel())->getTable(), "id")
                ]
            ]
        );
    }

    /**
     * 门店自检 - 自检任务详情校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function invalidSingleTaskValidate(array $params)
    {
        return self::getInstance()->validate(
            [
                "shopId",
                "id",
                "cruiseOrderId"
            ],
            $params,
            [
                "shopId"        => [
                    "required",
                    "int",
                    Rule::exists((new ShopModel())->getTable(), "id")
                ],
                "cruiseOrderId" => [
                    "required",
                    "int",
                    Rule::exists((new CruiseOrderModel())->getTable(), "id")
                ],
                "id"            => [
                    "required",
                    "int",
                    Rule::exists((new CruiseCheckSelfDetailModel())->getTable(), "id")
                        ->where("shopId", $params["shopId"] ?? 0)
                        ->where("cruiseOrderId", $params["cruiseOrderId"] ?? 0)
                ]
            ]
        );
    }

    /**
     * 门店自检 - 自检任务列表校验
     *
     * @param array $params
     * @return MessageBag|object
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public static function shopSelfCheckTaskListV2Validate(array $params)
    {
        return self::getInstance()->validate(
            [
                "shopId"
            ],
            $params,
            [
                "shopId" => [
                    "required",
                    "int",
                    Rule::exists((new ShopModel())->getTable(), "id")
                ]
            ]
        );
    }
}
